From eca331dcd43b940459dd28643063df5e41cd391d Mon Sep 17 00:00:00 2001 From: "cl349@freefall.cl.cam.ac.uk" Date: Tue, 9 Nov 2004 11:35:28 +0000 Subject: [PATCH] bitkeeper revision 1.1159.1.395 (4190ab80qQIIPeM49q40ES01DxL7Ng) Move shared_info pointer from exec_domain to domain and add vcpu_info pointer in exec_domain. --- xen/arch/x86/domain.c | 22 ++++---- xen/arch/x86/irq.c | 2 +- xen/arch/x86/time.c | 2 +- xen/arch/x86/traps.c | 8 +-- xen/arch/x86/x86_32/entry.S | 26 +++++----- xen/arch/x86/x86_32/seg_fixup.c | 2 +- xen/common/dom0_ops.c | 2 +- xen/common/domain.c | 4 +- xen/common/keyhandler.c | 6 +-- xen/common/schedule.c | 10 ++-- xen/include/asm-x86/x86_32/asm_defns.h | 22 ++++---- xen/include/public/xen.h | 71 ++++++++++++++------------ xen/include/xen/event.h | 8 +-- xen/include/xen/sched.h | 4 +- 14 files changed, 98 insertions(+), 91 deletions(-) diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c index af7fdc757e..e95fc73be2 100644 --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -215,19 +215,21 @@ void free_perdomain_pt(struct exec_domain *d) free_xenheap_page((unsigned long)d->mm.perdomain_pt); } -void arch_do_createdomain(struct exec_domain *d) +void arch_do_createdomain(struct exec_domain *ed) { + struct domain *d = ed->domain; d->shared_info = (void *)alloc_xenheap_page(); memset(d->shared_info, 0, PAGE_SIZE); + ed->vcpu_info = &d->shared_info->vcpu_data[ed->eid]; d->shared_info->arch.mfn_to_pfn_start = virt_to_phys(&machine_to_phys_mapping[0])>>PAGE_SHIFT; - SHARE_PFN_WITH_DOMAIN(virt_to_page(d->shared_info), d->domain); + SHARE_PFN_WITH_DOMAIN(virt_to_page(d->shared_info), d); machine_to_phys_mapping[virt_to_phys(d->shared_info) >> PAGE_SHIFT] = INVALID_P2M_ENTRY; - d->mm.perdomain_pt = (l1_pgentry_t *)alloc_xenheap_page(); - memset(d->mm.perdomain_pt, 0, PAGE_SIZE); - machine_to_phys_mapping[virt_to_phys(d->mm.perdomain_pt) >> + ed->mm.perdomain_pt = (l1_pgentry_t *)alloc_xenheap_page(); + memset(ed->mm.perdomain_pt, 0, PAGE_SIZE); + machine_to_phys_mapping[virt_to_phys(ed->mm.perdomain_pt) >> PAGE_SHIFT] = INVALID_P2M_ENTRY; } @@ -826,12 +828,12 @@ int construct_dom0(struct domain *p, } /* Set up shared-info area. */ - update_dom_time(ed->shared_info); - ed->shared_info->domain_time = 0; + update_dom_time(p->shared_info); + p->shared_info->domain_time = 0; /* Mask all upcalls... */ for ( i = 0; i < MAX_VIRT_CPUS; i++ ) - ed->shared_info->vcpu_data[i].evtchn_upcall_mask = 1; - ed->shared_info->n_vcpu = 1; + p->shared_info->vcpu_data[i].evtchn_upcall_mask = 1; + p->shared_info->n_vcpu = 1; /* Install the new page tables. */ __cli(); @@ -848,7 +850,7 @@ int construct_dom0(struct domain *p, si = (start_info_t *)vstartinfo_start; memset(si, 0, PAGE_SIZE); si->nr_pages = p->tot_pages; - si->shared_info = virt_to_phys(ed->shared_info); + si->shared_info = virt_to_phys(p->shared_info); si->flags = SIF_PRIVILEGED | SIF_INITDOMAIN; si->pt_base = vpt_start; si->nr_pt_frames = nr_pt_pages; diff --git a/xen/arch/x86/irq.c b/xen/arch/x86/irq.c index 5bbec081fd..32fa237747 100644 --- a/xen/arch/x86/irq.c +++ b/xen/arch/x86/irq.c @@ -212,7 +212,7 @@ int pirq_guest_unmask(struct domain *d) irq_desc_t *desc; unsigned int i, j, pirq; u32 m; - shared_info_t *s = d->exec_domain[0]->shared_info; + shared_info_t *s = d->shared_info; for ( i = 0; i < ARRAY_SIZE(d->pirq_mask); i++ ) { diff --git a/xen/arch/x86/time.c b/xen/arch/x86/time.c index be9f477ba5..06eed7c440 100644 --- a/xen/arch/x86/time.c +++ b/xen/arch/x86/time.c @@ -318,7 +318,7 @@ void do_settime(unsigned long secs, unsigned long usecs, u64 system_time_base) write_unlock_irq(&time_lock); - update_dom_time(current->shared_info); + update_dom_time(current->domain->shared_info); } diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c index 6164b15177..aff2f134e4 100644 --- a/xen/arch/x86/traps.c +++ b/xen/arch/x86/traps.c @@ -231,7 +231,7 @@ static inline void do_trap(int trapnr, char *str, gtb->cs = ti->cs; gtb->eip = ti->address; if ( TI_GET_IF(ti) ) - ed->shared_info->vcpu_data[0].evtchn_upcall_mask = 1; + ed->vcpu_info->evtchn_upcall_mask = 1; return; xen_fault: @@ -302,7 +302,7 @@ asmlinkage void do_int3(struct xen_regs *regs, long error_code) gtb->cs = ti->cs; gtb->eip = ti->address; if ( TI_GET_IF(ti) ) - ed->shared_info->vcpu_data[0].evtchn_upcall_mask = 1; + ed->vcpu_info->evtchn_upcall_mask = 1; } asmlinkage void do_double_fault(void) @@ -393,7 +393,7 @@ asmlinkage void do_page_fault(struct xen_regs *regs, long error_code) gtb->cs = ti->cs; gtb->eip = ti->address; if ( TI_GET_IF(ti) ) - ed->shared_info->vcpu_data[0].evtchn_upcall_mask = 1; + ed->vcpu_info->evtchn_upcall_mask = 1; return; xen_fault: @@ -510,7 +510,7 @@ asmlinkage void do_general_protection(struct xen_regs *regs, long error_code) gtb->cs = ti->cs; gtb->eip = ti->address; if ( TI_GET_IF(ti) ) - ed->shared_info->vcpu_data[0].evtchn_upcall_mask = 1; + ed->vcpu_info->evtchn_upcall_mask = 1; return; gp_in_kernel: diff --git a/xen/arch/x86/x86_32/entry.S b/xen/arch/x86/x86_32/entry.S index d0dba03cde..67b2009245 100644 --- a/xen/arch/x86/x86_32/entry.S +++ b/xen/arch/x86/x86_32/entry.S @@ -196,12 +196,12 @@ restore_all_guest: /* No special register assumptions */ failsafe_callback: GET_CURRENT(%ebx) - movl DOMAIN_processor(%ebx),%eax + movl EDOMAIN_processor(%ebx),%eax shl $4,%eax lea guest_trap_bounce(%eax),%edx - movl DOMAIN_failsafe_addr(%ebx),%eax + movl EDOMAIN_failsafe_addr(%ebx),%eax movl %eax,GTB_eip(%edx) - movl DOMAIN_failsafe_sel(%ebx),%eax + movl EDOMAIN_failsafe_sel(%ebx),%eax movw %ax,GTB_cs(%edx) call create_bounce_frame subl $16,%esi # add DS/ES/FS/GS to failsafe stack frame @@ -253,24 +253,24 @@ test_all_events: notl %ecx cli # tests must not race interrupts /*test_softirqs:*/ - movl DOMAIN_processor(%ebx),%eax + movl EDOMAIN_processor(%ebx),%eax shl $6,%eax # sizeof(irq_cpustat) == 64 test %ecx,SYMBOL_NAME(irq_stat)(%eax,1) jnz process_softirqs /*test_guest_events:*/ - movl DOMAIN_shared_info(%ebx),%eax - testb $0xFF,SHINFO_upcall_mask(%eax) + movl EDOMAIN_vcpu_info(%ebx),%eax + testb $0xFF,VCPUINFO_upcall_mask(%eax) jnz restore_all_guest - testb $0xFF,SHINFO_upcall_pending(%eax) + testb $0xFF,VCPUINFO_upcall_pending(%eax) jz restore_all_guest - movb $1,SHINFO_upcall_mask(%eax) # Upcalls are masked during delivery + movb $1,VCPUINFO_upcall_mask(%eax) # Upcalls are masked during delivery /*process_guest_events:*/ - movl DOMAIN_processor(%ebx),%edx + movl EDOMAIN_processor(%ebx),%edx shl $4,%edx # sizeof(guest_trap_bounce) == 16 lea guest_trap_bounce(%edx),%edx - movl DOMAIN_event_addr(%ebx),%eax + movl EDOMAIN_event_addr(%ebx),%eax movl %eax,GTB_eip(%edx) - movl DOMAIN_event_sel(%ebx),%eax + movl EDOMAIN_event_sel(%ebx),%eax movw %ax,GTB_cs(%edx) call create_bounce_frame jmp restore_all_guest @@ -290,7 +290,7 @@ create_bounce_frame: test $2,%cl jz 1f /* jump if returning to an existing ring-1 activation */ /* obtain ss/esp from TSS -- no current ring-1 activations */ - movl DOMAIN_processor(%ebx),%eax + movl EDOMAIN_processor(%ebx),%eax /* next 4 lines multiply %eax by 8320, which is sizeof(tss_struct) */ movl %eax, %ecx shll $7, %ecx @@ -362,7 +362,7 @@ crash_domain_fixup3: ALIGN process_guest_exception_and_events: - movl DOMAIN_processor(%ebx),%eax + movl EDOMAIN_processor(%ebx),%eax shl $4,%eax lea guest_trap_bounce(%eax),%edx testb $~0,GTB_flags(%edx) diff --git a/xen/arch/x86/x86_32/seg_fixup.c b/xen/arch/x86/x86_32/seg_fixup.c index 601ee27827..996fd09e8a 100644 --- a/xen/arch/x86/x86_32/seg_fixup.c +++ b/xen/arch/x86/x86_32/seg_fixup.c @@ -472,7 +472,7 @@ int gpf_emulate_4gb(struct xen_regs *regs) gtb->cs = ti->cs; gtb->eip = ti->address; if ( TI_GET_IF(ti) ) - d->shared_info->vcpu_data[0].evtchn_upcall_mask = 1; + d->vcpu_info->evtchn_upcall_mask = 1; } return 1; diff --git a/xen/common/dom0_ops.c b/xen/common/dom0_ops.c index e1046064a7..58484efb11 100644 --- a/xen/common/dom0_ops.c +++ b/xen/common/dom0_ops.c @@ -372,7 +372,7 @@ long do_dom0_op(dom0_op_t *u_dom0_op) op->u.getdomaininfo.max_pages = d->max_pages; op->u.getdomaininfo.cpu_time = ed->cpu_time; op->u.getdomaininfo.shared_info_frame = - __pa(ed->shared_info) >> PAGE_SHIFT; + __pa(d->shared_info) >> PAGE_SHIFT; if ( op->u.getdomaininfo.ctxt != NULL ) { diff --git a/xen/common/domain.c b/xen/common/domain.c index 5ca8697cbe..102afeff64 100644 --- a/xen/common/domain.c +++ b/xen/common/domain.c @@ -243,7 +243,7 @@ void domain_destruct(struct domain *d) for_each_exec_domain(d, ed) free_perdomain_pt(ed); - free_xenheap_page((unsigned long)d->exec_domain[0]->shared_info); + free_xenheap_page((unsigned long)d->shared_info); free_domain_struct(d); } @@ -278,7 +278,7 @@ int final_setup_guestos(struct domain *p, dom0_builddomain_t *builddomain) goto out; /* Set up the shared info structure. */ - update_dom_time(p->exec_domain[0]->shared_info); + update_dom_time(p->shared_info); set_bit(DF_CONSTRUCTED, &p->d_flags); diff --git a/xen/common/keyhandler.c b/xen/common/keyhandler.c index b8acae71a1..c5ab06145a 100644 --- a/xen/common/keyhandler.c +++ b/xen/common/keyhandler.c @@ -94,7 +94,7 @@ void do_task_queues(unsigned char key) } } - page = virt_to_page(d->exec_domain[0]->shared_info); + page = virt_to_page(d->shared_info); printk("Shared_info@%08x: caf=%08x, taf=%08x\n", page_to_phys(page), page->count_info, page->u.inuse.type_info); @@ -105,8 +105,8 @@ void do_task_queues(unsigned char key) ed->processor, test_bit(EDF_RUNNING, &ed->ed_flags) ? 'T':'F', ed->ed_flags, - ed->shared_info->vcpu_data[0].evtchn_upcall_pending, - ed->shared_info->vcpu_data[0].evtchn_upcall_mask); + ed->vcpu_info->evtchn_upcall_pending, + ed->vcpu_info->evtchn_upcall_mask); } printk("Notifying guest...\n"); send_guest_virq(d->exec_domain[0], VIRQ_DEBUG); diff --git a/xen/common/schedule.c b/xen/common/schedule.c index 3bc93b7bfa..22b97b6ef8 100644 --- a/xen/common/schedule.c +++ b/xen/common/schedule.c @@ -222,7 +222,7 @@ void domain_wake(struct exec_domain *d) long do_block(void) { ASSERT(current->id != IDLE_DOMAIN_ID); - current->shared_info->vcpu_data[0].evtchn_upcall_mask = 0; + current->vcpu_info->evtchn_upcall_mask = 0; set_bit(EDF_BLOCKED, ¤t->ed_flags); TRACE_2D(TRC_SCHED_BLOCK, current->id, current); __enter_scheduler(); @@ -390,7 +390,7 @@ void __enter_scheduler(void) /* Ensure that the domain has an up-to-date time base. */ if ( !is_idle_task(next->domain) ) - update_dom_time(next->shared_info); + update_dom_time(next->domain->shared_info); if ( unlikely(prev == next) ) return; @@ -468,7 +468,7 @@ static void t_timer_fn(unsigned long unused) TRACE_0D(TRC_SCHED_T_TIMER_FN); if ( !is_idle_task(p->domain) ) { - update_dom_time(p->shared_info); + update_dom_time(p->domain->shared_info); send_guest_virq(p, VIRQ_TIMER); } @@ -482,7 +482,7 @@ static void dom_timer_fn(unsigned long data) struct domain *p = (struct domain *)data; struct exec_domain *ed = p->exec_domain[0]; TRACE_0D(TRC_SCHED_DOM_TIMER_FN); - update_dom_time(ed->shared_info); + update_dom_time(p->shared_info); send_guest_virq(ed, VIRQ_TIMER); } @@ -496,7 +496,7 @@ static void fallback_timer_fn(unsigned long unused) TRACE_0D(TRC_SCHED_FALLBACK_TIMER_FN); if ( !is_idle_task(p) ) - update_dom_time(ed->shared_info); + update_dom_time(p->shared_info); fallback_timer[ed->processor].expires = NOW() + MILLISECS(500); add_ac_timer(&fallback_timer[ed->processor]); diff --git a/xen/include/asm-x86/x86_32/asm_defns.h b/xen/include/asm-x86/x86_32/asm_defns.h index 37efa67879..bca45ed53f 100644 --- a/xen/include/asm-x86/x86_32/asm_defns.h +++ b/xen/include/asm-x86/x86_32/asm_defns.h @@ -20,17 +20,17 @@ #define XREGS_fs 0x3C #define XREGS_gs 0x40 -/* Offsets in 'struct domain' --- AUTO-GENERATE ME! */ -#define DOMAIN_processor 0 -#define DOMAIN_shared_info 4 -#define DOMAIN_event_sel 8 -#define DOMAIN_event_addr 12 -#define DOMAIN_failsafe_sel 16 -#define DOMAIN_failsafe_addr 20 - -/* Offsets in shared_info_t --- AUTO-GENERATE ME! */ -#define SHINFO_upcall_pending /* 0 */ -#define SHINFO_upcall_mask 1 +/* Offsets in 'struct exec_domain' --- AUTO-GENERATE ME! */ +#define EDOMAIN_processor 0 +#define EDOMAIN_vcpu_info 4 +#define EDOMAIN_event_sel 8 +#define EDOMAIN_event_addr 12 +#define EDOMAIN_failsafe_sel 16 +#define EDOMAIN_failsafe_addr 20 + +/* Offsets in vcpu_info_t --- AUTO-GENERATE ME! */ +#define VCPUINFO_upcall_pending /* 0 */ +#define VCPUINFO_upcall_mask 1 /* Offsets in 'struct guest_trap_bounce' --- AUTO-GENERATE ME! */ #define GTB_error_code 0 diff --git a/xen/include/public/xen.h b/xen/include/public/xen.h index ca3cc054d6..eafb7bd639 100644 --- a/xen/include/public/xen.h +++ b/xen/include/public/xen.h @@ -253,46 +253,49 @@ typedef struct /* No support for multi-processor guests. */ #define MAX_VIRT_CPUS 4 +/* + * Per-VCPU information goes here. This will be cleaned up more when Xen + * actually supports multi-VCPU guests. + */ +typedef struct vcpu_info_st +{ + /* + * 'evtchn_upcall_pending' is written non-zero by Xen to indicate + * a pending notification for a particular VCPU. It is then cleared + * by the guest OS /before/ checking for pending work, thus avoiding + * a set-and-check race. Note that the mask is only accessed by Xen + * on the CPU that is currently hosting the VCPU. This means that the + * pending and mask flags can be updated by the guest without special + * synchronisation (i.e., no need for the x86 LOCK prefix). + * This may seem suboptimal because if the pending flag is set by + * a different CPU then an IPI may be scheduled even when the mask + * is set. However, note: + * 1. The task of 'interrupt holdoff' is covered by the per-event- + * channel mask bits. A 'noisy' event that is continually being + * triggered can be masked at source at this very precise + * granularity. + * 2. The main purpose of the per-VCPU mask is therefore to restrict + * reentrant execution: whether for concurrency control, or to + * prevent unbounded stack usage. Whatever the purpose, we expect + * that the mask will be asserted only for short periods at a time, + * and so the likelihood of a 'spurious' IPI is suitably small. + * The mask is read before making an event upcall to the guest: a + * non-zero mask therefore guarantees that the VCPU will not receive + * an upcall activation. The mask is cleared when the VCPU requests + * to block: this avoids wakeup-waiting races. + */ + u8 evtchn_upcall_pending; + u8 evtchn_upcall_mask; + u8 pad0, pad1; +} PACKED vcpu_info_t; + /* * Xen/guestos shared data -- pointer provided in start_info. * NB. We expect that this struct is smaller than a page. */ typedef struct shared_info_st { - /* - * Per-VCPU information goes here. This will be cleaned up more when Xen - * actually supports multi-VCPU guests. - */ - struct { - /* - * 'evtchn_upcall_pending' is written non-zero by Xen to indicate - * a pending notification for a particular VCPU. It is then cleared - * by the guest OS /before/ checking for pending work, thus avoiding - * a set-and-check race. Note that the mask is only accessed by Xen - * on the CPU that is currently hosting the VCPU. This means that the - * pending and mask flags can be updated by the guest without special - * synchronisation (i.e., no need for the x86 LOCK prefix). - * This may seem suboptimal because if the pending flag is set by - * a different CPU then an IPI may be scheduled even when the mask - * is set. However, note: - * 1. The task of 'interrupt holdoff' is covered by the per-event- - * channel mask bits. A 'noisy' event that is continually being - * triggered can be masked at source at this very precise - * granularity. - * 2. The main purpose of the per-VCPU mask is therefore to restrict - * reentrant execution: whether for concurrency control, or to - * prevent unbounded stack usage. Whatever the purpose, we expect - * that the mask will be asserted only for short periods at a time, - * and so the likelihood of a 'spurious' IPI is suitably small. - * The mask is read before making an event upcall to the guest: a - * non-zero mask therefore guarantees that the VCPU will not receive - * an upcall activation. The mask is cleared when the VCPU requests - * to block: this avoids wakeup-waiting races. - */ - u8 evtchn_upcall_pending; - u8 evtchn_upcall_mask; - u8 pad0, pad1; - } PACKED vcpu_data[MAX_VIRT_CPUS]; /* 0 */ + vcpu_info_t vcpu_data[MAX_VIRT_CPUS]; /* 0 */ u32 n_vcpu; diff --git a/xen/include/xen/event.h b/xen/include/xen/event.h index 86af2954a7..517b22ed4d 100644 --- a/xen/include/xen/event.h +++ b/xen/include/xen/event.h @@ -23,7 +23,7 @@ static inline void evtchn_set_pending(struct domain *d, int port) { struct exec_domain *ed = d->exec_domain[0]; - shared_info_t *s = ed->shared_info; + shared_info_t *s = d->shared_info; int running; /* These three operations must happen in strict order. */ @@ -32,7 +32,7 @@ static inline void evtchn_set_pending(struct domain *d, int port) !test_and_set_bit(port>>5, &s->evtchn_pending_sel) ) { /* The VCPU pending flag must be set /after/ update to evtchn-pend. */ - set_bit(0, &s->vcpu_data[0].evtchn_upcall_pending); + set_bit(0, &ed->vcpu_info->evtchn_upcall_pending); /* * NB1. 'flags' and 'processor' must be checked /after/ update of @@ -72,7 +72,7 @@ static inline void send_guest_pirq(struct domain *d, int pirq) } #define event_pending(_d) \ - ((_d)->shared_info->vcpu_data[0].evtchn_upcall_pending && \ - !(_d)->shared_info->vcpu_data[0].evtchn_upcall_mask) + ((_d)->vcpu_info->evtchn_upcall_pending && \ + !(_d)->vcpu_info->evtchn_upcall_mask) #endif /* __XEN_EVENT_H__ */ diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h index 83a160cc5c..17e58f6337 100644 --- a/xen/include/xen/sched.h +++ b/xen/include/xen/sched.h @@ -63,7 +63,7 @@ struct exec_domain u32 processor; /* 00: current processor */ /* An unsafe pointer into a shared data area. */ - shared_info_t *shared_info; /* 04: shared data area */ + vcpu_info_t *vcpu_info; /* 04: vcpu info pointer */ /* * Return vectors pushed to us by guest OS. @@ -106,6 +106,8 @@ struct domain { domid_t id; s_time_t create_time; + shared_info_t *shared_info; /* shared data area */ + spinlock_t page_alloc_lock; /* protects all the following fields */ struct list_head page_list; /* linked list, of size tot_pages */ struct list_head xenpage_list; /* linked list, of size xenheap_pages */ -- 2.30.2